package com.sx.mvvmlibs.http

import androidx.collection.ArrayMap
import com.blankj.utilcode.util.LogUtils
import com.google.gson.GsonBuilder
import com.sx.mvvmlibs.config.GlobalConfig
import com.sx.mvvmlibs.http.interceptor.HeaderInterceptor
import com.sx.mvvmlibs.http.interceptor.logging.Level
import com.sx.mvvmlibs.http.interceptor.logging.LoggingInterceptor
import com.sx.mvvmlibs.http.tools.HttpsUtils
import com.sx.mvvmlibs.http.tools.encrypts.EDRequestConverterFactory
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.internal.platform.Platform
import retrofit2.CallAdapter
import retrofit2.Retrofit
import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit

/**
 * @Author: YY
 * @Date: 2022/1/11
 * @Description: 单例模式的 网络请求
 */
object HttpRequest {

    // 缓存 IService
    private val mServiceMap = ArrayMap<String, Any>()

    // 默认的 baseUrl
    lateinit var mBaseUrl: String

    // 默认的请求头
    private lateinit var mHeader: ArrayMap<String, String>

    // 请求超时时间，秒为单位
    var mDefaultTimeout = 15

    // 客户端的Key
    var clientPriKey = ""

    // 服务端的Key
    var serverPubKey = ""

    /**
     * 添加默认的请求头
     */
    @JvmStatic
    fun addDefaultHeader(name: String, value: String) {
        if (!this::mHeader.isInitialized) {
            mHeader = ArrayMap()
        }
        mHeader[name] = value
    }

    @JvmStatic
    fun <T> getService(cls: Class<T>, host: String, vararg interceptors: Interceptor?): T {
        val name = cls.name
        var obj: Any? = mServiceMap[name]
        if (obj == null) {
            val httpClientBuilder = OkHttpClient.Builder()
            val sslParams = HttpsUtils.getSslSocketFactory()
            httpClientBuilder.sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager)
            // 超时时间
            httpClientBuilder.connectTimeout(mDefaultTimeout.toLong(), TimeUnit.SECONDS)
            httpClientBuilder.readTimeout(mDefaultTimeout.toLong(), TimeUnit.SECONDS)
            httpClientBuilder.writeTimeout(mDefaultTimeout.toLong(), TimeUnit.SECONDS)

            // 拦截器
            interceptors.forEach { interceptor ->
                interceptor?.let {
                    httpClientBuilder.addInterceptor(it)
                }
            }

            // 日志拦截器，是否打印由 LogUtil 控制
            httpClientBuilder
                .addInterceptor(
                    LoggingInterceptor
                        .Builder()
                        .loggable(GlobalConfig.gIsSaveLog)
                        // 打印的等级
                        .setLevel(Level.BASIC)
                        // 打印类型
                        .log(Platform.INFO)
                        // request 的 Tag
                        .request("Request")
                        // Response 的 Tag
                        .response("Response")
                        .build()
                )

            val client = httpClientBuilder.build()

            val builder = Retrofit.Builder().client(client)
                // 基础url
                .baseUrl(host)
                // JSON解析
                .addConverterFactory(GsonConverterFactory.create())
                //加解密工具
                .addConverterFactory(EDRequestConverterFactory.create(GSON, clientPriKey, serverPubKey))
                .addCallAdapterFactory(getRxJavaAdapter() as CallAdapter.Factory)

            obj = builder.build().create(cls)
            mServiceMap[name] = obj
        }
        @Suppress("UNCHECKED_CAST")
        return obj as T
    }

    /**
     * 设置了 [mBaseUrl] 后，可通过此方法获取 Service
     */
    @JvmStatic
    fun <T> getService(cls: Class<T>): T {
        if (!this::mBaseUrl.isInitialized) {
            throw RuntimeException("必须初始化 mBaseUrl")
        }
        if (this::mHeader.isInitialized) {
            val headers = HeaderInterceptor(mHeader)
            return getService(cls, mBaseUrl, headers)
        }
        return getService(cls, mBaseUrl, null)
    }

    /**
     * JSON序列化配置
     */
    private val GSON = GsonBuilder()
        .setDateFormat("yyyy-MM-dd hh:mm:ss")
        .setLenient()
        .create()

    /**
     * 获取Rx适配器
     */
    private fun getRxJavaAdapter(): Any? {
        try {
            return RxJava3CallAdapterFactory.create()
        } catch (e: Throwable) {
            e.printStackTrace()
        }
        return null
    }

}